package net.csdn.business.auth.permission;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;

import java.util.Collection;
import java.util.Set;

/**
 * @Auther: zhangyalei
 * @Date: 2022/11/21 14:49
 * @Description: 决策管理器，判断请求的url是通过还是阻断.
 */
@Slf4j
//@Component
public class UrlAccessDecisionManager implements AccessDecisionManager {

    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        log.info("当前路径需要的权限有{}", configAttributes);
        log.info("当前登录用户{}", JSONUtil.toJsonStr(authentication));
        // 当前访问的地址需要哪些用户角色
        for (ConfigAttribute configAttribute : configAttributes) {
            String needRole = configAttribute.getAttribute();
            // 需要登录权限，但是已经登录的，直接通过
            if ("login".equals(needRole)) {
                if (authentication instanceof AnonymousAuthenticationToken) {
                    throw new AccessDeniedException("未登录或者登录失效");
                }else {
                    return;
                }
            }
            //如果是oauth2认证服务认证的用户，需要校验scope
            if(authentication instanceof OAuth2Authentication){
                OAuth2Authentication oAuth2Authentication=(OAuth2Authentication)authentication;
                OAuth2Request oAuth2Request=oAuth2Authentication.getOAuth2Request();
                Set<String> scopes=oAuth2Request.getScope();
                if(scopes==null||scopes.size()==0){
                    throw new AccessDeniedException("没有权限访问");
                }
                if(scopes.contains(needRole)){
                    return;
                }
            }
        }
        throw new AccessDeniedException("没有权限访问");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
